package cn.wit.luohui.day13;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class DemoProducerAndConsumer {
public static void main(String[] args) {
	ExecutorService service=Executors.newFixedThreadPool(10);//线程池，创建10个线程

	Factory factory=new Factory();
	
	service.execute(new Producer(factory));
	service.execute(new Consumer(factory));
	
	service.shutdown();//shutdown() 方法在终止前允许执行以前提交的任务
}
}
class Producer implements Runnable{
private Factory factory;
	public Producer(Factory f) {
		this.factory=f;
	}

	@Override
	public void run() {
		//不断的生产egg
		try {
		while(true) {
			//往工厂里面放入一个产品
		factory.put();
		Thread.sleep((long)(Math.random()*10));//Math.random()为double类型，而sleep为long
		}
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
	}
	
}
class Consumer implements Runnable{
private Factory f;
	public Consumer(Factory f) {
		this.f=f;
	}

	@Override
	public void run() {
		//消费者买鸡蛋
		try {
		while(true) {
			f.buy();
			Thread.sleep((long)(Math.random()*10));
		}
		}catch(InterruptedException e) {
			//InterruptedException出现一般都是因为在线程执行的时候被打断
			e.printStackTrace();
		}
	}
	
}
class Factory{
	private static final int MAX=10;//每次放10个
	List<Integer>eggs=new ArrayList<>();//用一个集合来装生产的鸡蛋
	
	int id=1;//鸡蛋编号
	
	//synchronized给对象加上了锁，同时只有一个可以访问对象的方法（排队）
	
	//消费一个产品
	public synchronized void buy() {
		if(eggs.size()==0) {
			System.out.println("鸡蛋卖完了。。。白跑一趟");
			
			try {
				wait();//让当前线程处于等待状态。并且释放了当前对象的锁
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
		}
		if(eggs.size()==0)return;//双重检查
		
		Integer last=eggs.remove(eggs.size()-1);//买掉一个就
		System.out.println("买到了一个鸡蛋。。。#"+last);
		
		notify();//notify()方法:唤醒当前等待队列中的第一个相关线程
		
	}
	//生产一个产品
	public synchronized void put() {
		if(eggs.size()>=MAX) {
			System.out.println("放不下了。。。鸡蛋扔掉。");
			
			
			try {
				System.out.println("等等吧。总会有人买走鸡蛋的。。");
				wait();
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
		}
		System.out.println("放入了一个鸡蛋。。。#"+id);
		eggs.add(id++);
		
		notify();// 唤醒其它处于等待的线程
	}
}